﻿/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * The Original Code is tyzoh.jp code.
 *
 * The Initial Developer of the Original Code is Kazutaka Kurihara.
 * Portions created by the Initial Developer are Copyright (C) 2007
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** */
using System;
using System.Drawing;

namespace Qurihara.Anm
{
    /*
/// <summary>
/// RectMoveAnm
/// </summary>
public class RectMoveAnm : IAnm
{
    public static FPSManager fpsManager = new FPSManager(30);
    public RectMoveAnm(IAnmElement ae,Rectangle initR,Rectangle destR,int duration,int intvl,AnmType at)
    {
        ae.Anm = this;
        timer = new Timer();
        timer.Tick += new EventHandler(TickEventHandler);
        timer.Interval = intvl;
        timer.Enabled = false;
        switch(at)
        {
            case RectMoveAnm.AnmType.Cubic:
                interpolate = new CubicInterpolate(initR,destR,duration,intvl);
                break;
            case RectMoveAnm.AnmType.Linear:
            default:
                interpolate = new LinearInterpolate(initR,destR,duration,intvl);
                break;
        }
        anmElement = ae;
    }
    protected System.Windows.Forms.Timer timer;
    protected IAnmElement anmElement;
    protected Interpolate interpolate;
    protected void TickEventHandler(object o,EventArgs e)
    {
        //anmElement.Invalidate();
        RectMoveAnm.fpsManager.Enqueue(anmElement);
        Rectangle r;
        if (interpolate.Next(out r))
        {
            anmElement.BoundingBox = r;
            RectMoveAnm.fpsManager.Enqueue(anmElement);
            //anmElement.Invalidate();
        }
        else
        {
            this.Stop();
            FinishedFire();
        }
    }
    public void Start()
    {
        RectMoveAnm.fpsManager.Enqueue(anmElement);
        //anmElement.Invalidate();
        timer.Enabled = true;
        timer.Start();
        anmElement.BoundingBox = interpolate.InitRectangle;
        //anmElement.Invalidate();
        RectMoveAnm.fpsManager.Enqueue(anmElement);
    }
    public void Stop()
    {
        RectMoveAnm.fpsManager.Enqueue(anmElement);
        //anmElement.Invalidate();
        timer.Stop();
        timer.Enabled = false;
        anmElement.BoundingBox = interpolate.DestRectangle;
        RectMoveAnm.fpsManager.Enqueue(anmElement);
        //anmElement.Invalidate();
    }
    public event EventHandler AnmFinishedHandler;
    public bool IsActive
    {
        get{return timer.Enabled;}
    }

    protected void FinishedFire()
    {
        if(AnmFinishedHandler != null) AnmFinishedHandler(this,new EventArgs());
    }

    #region Interpolate
    protected class Interpolate
    {
        protected int curCount,endCount;
        protected Rectangle initRectangle,destRectangle;
        protected int durationTime,interval;
        public Interpolate(Rectangle initR,Rectangle destR,int duration,int intvl)
        {
            durationTime = duration;
            initRectangle = initR;
            destRectangle = destR;
            curCount = 0;
            endCount = (int)(duration / intvl);
        }
        public Rectangle InitRectangle
        {
            get{return initRectangle;}
        }
        public Rectangle DestRectangle
        {
            get{return destRectangle;}
        }
        public virtual bool Next(out Rectangle nextRectangle)
        {
            nextRectangle = destRectangle;
            return false;
        }
        protected Rectangle CalcRectangle(float s)
        {
            int x,y,width,height;
            x = (int)((1-s)*initRectangle.X + s*destRectangle.X);
            y = (int)((1-s)*initRectangle.Y + s*destRectangle.Y);
            width = (int)((1-s)*initRectangle.Width + s*destRectangle.Width);
            height = (int)((1-s)*initRectangle.Height + s*destRectangle.Height);
            return new Rectangle(x,y,width,height);
        }

    }

    protected class LinearInterpolate : Interpolate
    {
        public LinearInterpolate(Rectangle initR,Rectangle destR,int duration,int intvl):base(initR,destR,duration,intvl)
        {
        }
        public override bool Next(out Rectangle nextRectangle)
        {
            curCount++;
            if(curCount == endCount) 
            {
                nextRectangle = destRectangle;
                return false;
            }
            float s = (float)curCount / (float)endCount;
            nextRectangle = CalcRectangle(s);
            return true;
        }
    }
    protected class CubicInterpolate : Interpolate
    {
        public static float InitialVelocity = 2.0f;
        public CubicInterpolate(Rectangle initR,Rectangle destR,int duration,int intvl):base(initR,destR,duration,intvl)
        {
        }
        public override bool Next(out Rectangle nextRectangle)
        {
            curCount++;
            if(curCount == endCount) 
            {
                nextRectangle = destRectangle;
                return false;
            }
            //float tmp = (float)curCount / (float)endCount - 1;
            //float s = -CubicInterpolate.InitialVelocity*tmp*tmp +1; 
            float tmp = (float)curCount / (float)endCount;
            float s = tmp*(CubicInterpolate.InitialVelocity*(tmp-1)*(tmp-1) -(tmp-1)+1); 
            nextRectangle = CalcRectangle(s);
            return true;
        }
    }
    #endregion

    public enum AnmType
    {
        Linear,
        Cubic
    }
}
*/

    /// <summary>
    /// AnmBase
    /// </summary>
    public abstract class AnmBase : IAnm
    {
        public static FPSManager fpsManager = new FPSManager(30);
        public AnmBase(IAnmElement ae, int dura)
        {
            timer = RectMoveAnm.fpsManager.Timer;
            //timer.Interval = intvl;

            duration = dura;
            anmElement = ae;
        }

        protected float currentTime;
        protected int duration;
        protected DateTime startTime;
        protected System.EventHandler tickEventHandler;
        protected bool isActive = false;
        protected System.Windows.Forms.Timer timer;
        protected IAnmElement anmElement;
        protected void TickEventHandler(object o, EventArgs e)
        {
            SetTime();
            Step();
        }
        private void SetTime()
        {
            TimeSpan elapsed = DateTime.Now.Subtract(startTime);
            currentTime = (float)(elapsed.TotalMilliseconds / (double)duration);
            if (currentTime > 1.0f) currentTime = 1.0f;
        }
        protected void RegisterTimer()
        {
            tickEventHandler = new EventHandler(TickEventHandler);
            timer.Tick += tickEventHandler;
            //fpsManager.Add(this);
            isActive = true;
            startTime = DateTime.Now;
            SetTime();
        }
        protected void UnRegisterTimer()
        {
            if (tickEventHandler != null) timer.Tick -= tickEventHandler;
            //fpsManager.Remove(this);
            isActive = false;
        }

        public abstract void Init();
        public abstract void Start();
        public abstract void Step();
        public abstract void Finish();
        public abstract void Abort();
        public virtual bool IsActive
        {
            get { return isActive; }
        }
        public abstract event EventHandler AnmFinishedHandler;

    }

    /// <summary>
    /// WaitAnm
    /// </summary>
    public class WaitAnm : AnmBase
    {
        //protected int endCount,count;
        public WaitAnm(int dura)
            : base(null, dura)
        {
            //endCount = dura / AnmBase.fpsManager.Interval;
        }
        public override void Init()
        {
        }
        public override void Start()
        {
            //count = 0;
            RegisterTimer();
        }

        public override void Step()
        {
            if (currentTime >= 1.0f)
            {
                Finish();
                FinishedFire();
            }
            //			if (count >= endCount)
            //			{
            //				Finish();
            //				FinishedFire();
            //			}
            //			else
            //			{
            //				count++;
            //			}
        }
        public override void Finish()
        {
            Abort();
        }
        public override void Abort()
        {
            UnRegisterTimer();
        }
        public override event EventHandler AnmFinishedHandler;

        protected void FinishedFire()
        {
            if (AnmFinishedHandler != null) AnmFinishedHandler(this, new EventArgs());
        }

    }

    /// <summary>
    /// RectMoveAnm
    /// </summary>
    public class RectMoveAnm : AnmBase
    {
        public RectMoveAnm(IAnmElement ae, Rectangle initR, Rectangle destR, int duration, AnmType at)
            : base(ae, duration)
        {
            ae.Anm = this;
            switch (at)
            {
                case RectMoveAnm.AnmType.Cubic:
                    //interpolate = new CubicInterpolate(initR,destR,duration,intvl);
                    interpolate = new CubicInterpolate(initR, destR, duration, AnmBase.fpsManager.Interval);
                    break;
                case RectMoveAnm.AnmType.Linear:
                default:
                    //interpolate = new LinearInterpolate(initR,destR,duration,intvl);
                    interpolate = new LinearInterpolate(initR, destR, duration, AnmBase.fpsManager.Interval);
                    break;
            }
        }
        protected Interpolate interpolate;
        public override void Init()
        {
            interpolate.Init();
        }
        public override void Start()
        {
            //RectMoveAnm.fpsManager.Enqueue(anmElement);
            anmElement.Invalidate();
            //timer.Enabled = true;
            //timer.Start();
            anmElement.BoundingBox = interpolate.InitRectangle;
            anmElement.Invalidate();
            //RectMoveAnm.fpsManager.Enqueue(anmElement);
            RegisterTimer();
        }

        public override void Step()
        {
            anmElement.Invalidate();
            //RectMoveAnm.fpsManager.Enqueue(anmElement);
            Rectangle r;
            //if (interpolate.Next(out r))
            if (interpolate.GetRect(currentTime, out r))
            {
                anmElement.BoundingBox = r;
                //RectMoveAnm.fpsManager.Enqueue(anmElement);
                anmElement.Invalidate();
            }
            else
            {
                this.Finish();
                FinishedFire();
            }
        }
        public override void Finish()
        {
            //RectMoveAnm.fpsManager.Enqueue(anmElement);
            anmElement.Invalidate();
            //timer.Stop();
            //timer.Enabled = false;
            anmElement.BoundingBox = interpolate.DestRectangle;
            //RectMoveAnm.fpsManager.Enqueue(anmElement);
            anmElement.Invalidate();
            Abort();
        }
        public override void Abort()
        {
            UnRegisterTimer();
        }
        public override event EventHandler AnmFinishedHandler;

        protected void FinishedFire()
        {
            if (AnmFinishedHandler != null) AnmFinishedHandler(this, new EventArgs());
        }

        #region Interpolate
        protected class Interpolate
        {
            protected int curCount, endCount;
            protected Rectangle initRectangle, destRectangle;
            protected int durationTime, interval;
            public Interpolate(Rectangle initR, Rectangle destR, int duration, int intvl)
            {
                durationTime = duration;
                interval = intvl;
                initRectangle = initR;
                destRectangle = destR;
                Init();
            }
            public void Init()
            {
                curCount = 0;
                endCount = (int)(durationTime / interval);
            }
            public Rectangle InitRectangle
            {
                get { return initRectangle; }
            }
            public Rectangle DestRectangle
            {
                get { return destRectangle; }
            }
            //			public virtual bool Next(out Rectangle nextRectangle)
            //			{
            //				nextRectangle = destRectangle;
            //				return false;
            //			}
            public virtual bool GetRect(float pos, out Rectangle nextRectangle)
            {
                nextRectangle = destRectangle;
                return false;
            }
            protected Rectangle CalcRectangle(float s)
            {
                int x, y, width, height;
                x = (int)((1 - s) * initRectangle.X + s * destRectangle.X);
                y = (int)((1 - s) * initRectangle.Y + s * destRectangle.Y);
                width = (int)((1 - s) * initRectangle.Width + s * destRectangle.Width);
                height = (int)((1 - s) * initRectangle.Height + s * destRectangle.Height);
                return new Rectangle(x, y, width, height);
            }

        }

        protected class LinearInterpolate : Interpolate
        {
            public LinearInterpolate(Rectangle initR, Rectangle destR, int duration, int intvl)
                : base(initR, destR, duration, intvl)
            {
            }
            //			public override bool Next(out Rectangle nextRectangle)
            //			{
            //				curCount++;
            //				if(curCount == endCount) 
            //				{
            //					nextRectangle = destRectangle;
            //					return false;
            //				}
            //				float s = (float)curCount / (float)endCount;
            //				nextRectangle = CalcRectangle(s);
            //				return true;
            //			}
            public override bool GetRect(float pos, out Rectangle nextRectangle)
            {
                if (pos >= 1.0f)
                {
                    nextRectangle = destRectangle;
                    return false;
                }
                nextRectangle = CalcRectangle(pos);
                return true;
            }
        }
        protected class CubicInterpolate : Interpolate
        {
            public static float InitialVelocity = 2.0f;
            public CubicInterpolate(Rectangle initR, Rectangle destR, int duration, int intvl)
                : base(initR, destR, duration, intvl)
            {
            }
            //			public override bool Next(out Rectangle nextRectangle)
            //			{
            //				curCount++;
            //				if(curCount == endCount) 
            //				{
            //					nextRectangle = destRectangle;
            //					return false;
            //				}
            //				//float tmp = (float)curCount / (float)endCount - 1;
            //				//float s = -CubicInterpolate.InitialVelocity*tmp*tmp +1; 
            //				float tmp = (float)curCount / (float)endCount;
            //				float s = tmp*(CubicInterpolate.InitialVelocity*(tmp-1)*(tmp-1) -(tmp-1)+1); 
            //				nextRectangle = CalcRectangle(s);
            //				return true;
            //			}
            public override bool GetRect(float pos, out Rectangle nextRectangle)
            {
                if (pos >= 1.0f)
                {
                    nextRectangle = destRectangle;
                    return false;
                }
                float s = pos * (CubicInterpolate.InitialVelocity * (pos - 1) * (pos - 1) - (pos - 1) + 1);
                nextRectangle = CalcRectangle(s);
                return true;
            }
        }
        #endregion

        public enum AnmType
        {
            Linear,
            Cubic
        }
    }

    /// <summary>
    /// PlayBackAnmWrapper
    /// </summary>
    public class PlayBackAnmWrapper : IAnm
    {
        protected IAnm anm;
        protected PlayBackAnmWrapper() { }
        public PlayBackAnmWrapper(IAnmElement ae, int duration)
        {
            if (ae is IPlayBackAnmElement)
            {
                anm = new PlayBackAnm((IPlayBackAnmElement)ae, duration);
            }
            else
            {
                anm = new AppearAnm(ae, duration);
            }

            anm.AnmFinishedHandler += new EventHandler(FinishedHandler);

            ae.Anm = this;// should be at the bottom to override ae.anm = rectmoveanm
        }
        public void Init()
        {
            anm.Init();
        }
        public void Start()
        {
            anm.Start();
        }
        public void Step()
        {
            anm.Step();
        }
        public void Finish()
        {
            anm.Finish();
        }
        public void Abort()
        {
            anm.Abort();
        }
        public event EventHandler AnmFinishedHandler;
        public bool IsActive
        {
            get { return anm.IsActive; }
        }

        protected void FinishedHandler(object o, EventArgs e)
        {
            if (AnmFinishedHandler != null) AnmFinishedHandler(this, new EventArgs());
        }
    }

    /// <summary>
    /// PlayBackAnmWrapper2
    /// </summary>
    public class PlayBackAnmWrapper2 : PlayBackAnmWrapper
    {
        public PlayBackAnmWrapper2(IAnmElement ae, Rectangle parentR, int duration)
        {
            if (ae is IPlayBackAnmElement)
            {
                anm = new PlayBackAnm((IPlayBackAnmElement)ae, duration);
            }
            else
            {
                anm = new SlideInAnm(ae, parentR, ae.BoundingBox, duration, RectMoveAnm.AnmType.Cubic, SlideInAnm.From.Right);
            }

            anm.AnmFinishedHandler += new EventHandler(base.FinishedHandler);

            ae.Anm = this;// should be at the bottom to override ae.anm = rectmoveanm
        }
    }

    /// <summary>
    /// PlayBackAnm
    /// </summary>
    public class PlayBackAnm : AnmBase
    {
        protected IAnm anm;
        protected IPlayBackAnmElement playBackAnmElement;
        //protected float step;
        public PlayBackAnm(IPlayBackAnmElement ape, int duration)
            : base(ape, duration)
        {
            ape.Anm = this;
            playBackAnmElement = ape;
            //step = (float)intvl/(float)duration;
        }
        public override void Init()
        {
            playBackAnmElement.Visible = false;
        }
        public override void Start()
        {
            playBackAnmElement.Visible = true;
            playBackAnmElement.Invalidate();
            playBackAnmElement.PlayPosition = 0.0f;
            playBackAnmElement.Invalidate();
            RegisterTimer();
        }

        public override void Step()
        {
            playBackAnmElement.Invalidate();
            //playBackAnmElement.PlayPosition += step;
            playBackAnmElement.PlayPosition = currentTime;
            if (playBackAnmElement.PlayPosition < 1.0f)
            {
                playBackAnmElement.Invalidate();
            }
            else
            {
                this.Finish();
                FinishedFire();
            }
        }
        public override void Finish()
        {
            playBackAnmElement.Invalidate();
            playBackAnmElement.PlayPosition = 1.0f;
            playBackAnmElement.Invalidate();
            Abort();
        }
        public override void Abort()
        {
            UnRegisterTimer();
        }
        public override event EventHandler AnmFinishedHandler;

        protected void FinishedFire()
        {
            if (AnmFinishedHandler != null) AnmFinishedHandler(this, new EventArgs());
        }
    }


    /*
    /// <summary>
    /// RectMoveAnm
    /// </summary>
    public class RectMoveAnm : IAnm
    {
        public static FPSManager fpsManager = new FPSManager(30);
        public RectMoveAnm(IAnmElement ae,Rectangle initR,Rectangle destR,int duration,int intvl,AnmType at)
        {
            ae.Anm = this;
            timer = RectMoveAnm.fpsManager.Timer;
            //timer.Interval = intvl;
            switch(at)
            {
                case RectMoveAnm.AnmType.Cubic:
                    interpolate = new CubicInterpolate(initR,destR,duration,intvl);
                    break;
                case RectMoveAnm.AnmType.Linear:
                default:
                    interpolate = new LinearInterpolate(initR,destR,duration,intvl);
                    break;
            }
            anmElement = ae;
        }
        protected System.EventHandler tickEventHandler;
        protected bool isActive = false;
        protected System.Windows.Forms.Timer timer;
        protected IAnmElement anmElement;
        protected Interpolate interpolate;
        protected void TickEventHandler(object o,EventArgs e)
        {
            Step();
        }
        public void Start()
        {
            //RectMoveAnm.fpsManager.Enqueue(anmElement);
            anmElement.Invalidate();
            //timer.Enabled = true;
            //timer.Start();
            anmElement.BoundingBox = interpolate.InitRectangle;
            anmElement.Invalidate();
            //RectMoveAnm.fpsManager.Enqueue(anmElement);
            tickEventHandler = new EventHandler(TickEventHandler);
            timer.Tick += tickEventHandler;
            isActive = true;
        }
        public void Step()
        {
            anmElement.Invalidate();
            //RectMoveAnm.fpsManager.Enqueue(anmElement);
            Rectangle r;
            if (interpolate.Next(out r))
            {
                anmElement.BoundingBox = r;
                //RectMoveAnm.fpsManager.Enqueue(anmElement);
                anmElement.Invalidate();
            }
            else
            {
                this.Finish();
                FinishedFire();
            }
        }
        public void Finish()
        {
            //RectMoveAnm.fpsManager.Enqueue(anmElement);
            anmElement.Invalidate();
            //timer.Stop();
            //timer.Enabled = false;
            anmElement.BoundingBox = interpolate.DestRectangle;
            //RectMoveAnm.fpsManager.Enqueue(anmElement);
            anmElement.Invalidate();
            Abort();
        }
        public void Abort()
        {
            if (tickEventHandler != null) timer.Tick -= tickEventHandler;
            isActive = false;
        }
        public event EventHandler AnmFinishedHandler;
        public bool IsActive
        {
            get{return isActive;}
        }

        protected void FinishedFire()
        {
            if(AnmFinishedHandler != null) AnmFinishedHandler(this,new EventArgs());
        }

    #region Interpolate
        protected class Interpolate
        {
            protected int curCount,endCount;
            protected Rectangle initRectangle,destRectangle;
            protected int durationTime,interval;
            public Interpolate(Rectangle initR,Rectangle destR,int duration,int intvl)
            {
                durationTime = duration;
                initRectangle = initR;
                destRectangle = destR;
                curCount = 0;
                endCount = (int)(duration / intvl);
            }
            public Rectangle InitRectangle
            {
                get{return initRectangle;}
            }
            public Rectangle DestRectangle
            {
                get{return destRectangle;}
            }
            public virtual bool Next(out Rectangle nextRectangle)
            {
                nextRectangle = destRectangle;
                return false;
            }
            protected Rectangle CalcRectangle(float s)
            {
                int x,y,width,height;
                x = (int)((1-s)*initRectangle.X + s*destRectangle.X);
                y = (int)((1-s)*initRectangle.Y + s*destRectangle.Y);
                width = (int)((1-s)*initRectangle.Width + s*destRectangle.Width);
                height = (int)((1-s)*initRectangle.Height + s*destRectangle.Height);
                return new Rectangle(x,y,width,height);
            }

        }

        protected class LinearInterpolate : Interpolate
        {
            public LinearInterpolate(Rectangle initR,Rectangle destR,int duration,int intvl):base(initR,destR,duration,intvl)
            {
            }
            public override bool Next(out Rectangle nextRectangle)
            {
                curCount++;
                if(curCount == endCount) 
                {
                    nextRectangle = destRectangle;
                    return false;
                }
                float s = (float)curCount / (float)endCount;
                nextRectangle = CalcRectangle(s);
                return true;
            }
        }
        protected class CubicInterpolate : Interpolate
        {
            public static float InitialVelocity = 2.0f;
            public CubicInterpolate(Rectangle initR,Rectangle destR,int duration,int intvl):base(initR,destR,duration,intvl)
            {
            }
            public override bool Next(out Rectangle nextRectangle)
            {
                curCount++;
                if(curCount == endCount) 
                {
                    nextRectangle = destRectangle;
                    return false;
                }
                //float tmp = (float)curCount / (float)endCount - 1;
                //float s = -CubicInterpolate.InitialVelocity*tmp*tmp +1; 
                float tmp = (float)curCount / (float)endCount;
                float s = tmp*(CubicInterpolate.InitialVelocity*(tmp-1)*(tmp-1) -(tmp-1)+1); 
                nextRectangle = CalcRectangle(s);
                return true;
            }
        }
    #endregion

        public enum AnmType
        {
            Linear,
            Cubic
        }
    }
*/

    public class AppearAnm : IAnm
    {
        protected RectMoveAnm anm;
        protected IAnmElement anmElement;
        public AppearAnm(IAnmElement ae, int duration)
        {
            anm = new RectMoveAnm(ae,
                new Rectangle(-ae.BoundingBox.Width, -ae.BoundingBox.Height, ae.BoundingBox.Width, ae.BoundingBox.Height),
                ae.BoundingBox, duration, RectMoveAnm.AnmType.Linear);
            anm.AnmFinishedHandler += new EventHandler(FinishedHandler);

            ae.Anm = this;// should be at the bottom to override ae.anm = rectmoveanm
            anmElement = ae;
        }
        public void Init()
        {
            anmElement.Visible = false;
            anm.Init();
        }
        public void Start()
        {
            anmElement.Visible = true;
            anm.Start();
        }
        public void Step()
        {
            anm.Step();
        }
        public void Finish()
        {
            anmElement.Visible = true;
            anm.Finish();
        }
        public void Abort()
        {
            anmElement.Visible = true;
            anm.Abort();
        }
        public event EventHandler AnmFinishedHandler;
        public bool IsActive
        {
            get { return anm.IsActive; }
        }

        protected void FinishedHandler(object o, EventArgs e)
        {
            if (AnmFinishedHandler != null) AnmFinishedHandler(this, new EventArgs());
        }
    }
    /*
    public class AppearAnm : IAnm
    {
        protected WaitAnm wanm;
        protected IAnmElement anmElement;
        public AppearAnm(IAnmElement ae,int duration,int intvl): this(ae,duration)
        {
        }
        public AppearAnm(IAnmElement ae,int duration)
        {
            wanm = new WaitAnm(duration);
            ae.Anm = this;// should be at the bottom to override ae.anm = rectmoveanm
            anmElement = ae;
        }
        public void Init()
        {
            anmElement.Visible = false;			
        }
        public void Start()
        {
            wanm.Start();
        }
        public void Step()
        {
            wanm.Step();
        }
        public void Finish()
        {
            anmElement.Visible = true;
            wanm.Finish();
        }
        public void Abort()
        {
            anmElement.Visible = true;
            wanm.Abort();
        }
        public event EventHandler AnmFinishedHandler;
        public bool IsActive
        {
            get{return wanm.IsActive;}
        }

        protected void FinishedHandler(object o,EventArgs e)
        {
            if (AnmFinishedHandler != null) AnmFinishedHandler(this,new EventArgs());
        }
    }
*/
    public class SlideInAnm : IAnm
    {
        public enum From
        {
            Top,
            Bottom,
            Left,
            Right
        }
        protected RectMoveAnm anm;
        protected IAnmElement anmElement;
        public SlideInAnm(IAnmElement ae, Rectangle parentR, Rectangle destR, int duration, RectMoveAnm.AnmType at, From f)
        {
            Rectangle initR;
            switch (f)
            {
                case From.Top:
                    initR = new Rectangle(destR.X, parentR.Top - destR.Height, destR.Width, destR.Height);
                    break;
                case From.Bottom:
                    initR = new Rectangle(destR.X, parentR.Bottom, destR.Width, destR.Height);
                    break;
                case From.Left:
                    initR = new Rectangle(parentR.Left - destR.Width, destR.Y, destR.Width, destR.Height);
                    break;
                case From.Right:
                default:
                    initR = new Rectangle(parentR.Right, destR.Y, destR.Width, destR.Height);
                    break;
            }
            anm = new RectMoveAnm(ae, initR, destR, duration, at);
            anm.AnmFinishedHandler += new EventHandler(FinishedHandler);

            ae.Anm = this;// should be at the bottom to override ae.anm = rectmoveanm
            anmElement = ae;
        }
        public void Init()
        {
            anmElement.Visible = false;
            anm.Init();
        }
        public void Start()
        {
            anmElement.Visible = true;
            anm.Start();
        }
        public void Step()
        {
            anm.Step();
        }
        public void Finish()
        {
            anmElement.Visible = true;
            anm.Finish();
        }
        public void Abort()
        {
            anmElement.Visible = true;
            anm.Abort();
        }
        public event EventHandler AnmFinishedHandler;
        public bool IsActive
        {
            get { return anm.IsActive; }
        }

        protected void FinishedHandler(object o, EventArgs e)
        {
            if (AnmFinishedHandler != null) AnmFinishedHandler(this, new EventArgs());
        }
    }

    public class JumpAnm : IAnm
    {
        protected RectMoveAnm anmUp;
        protected RectMoveAnm anmDown;
        protected IAnmElement anmElement;

        public JumpAnm(IAnmElement ae, int jumpHeight, int duration)
        {
            Rectangle top = new Rectangle(ae.BoundingBox.Left, ae.BoundingBox.Top - jumpHeight
                , ae.BoundingBox.Width, ae.BoundingBox.Height);
            anmUp = new RectMoveAnm(ae, ae.BoundingBox, top, duration / 2, RectMoveAnm.AnmType.Cubic);
            anmUp.AnmFinishedHandler += new EventHandler(TurningPointHandler);
            anmDown = new RectMoveAnm(ae, top, ae.BoundingBox, duration / 2, RectMoveAnm.AnmType.Cubic);
            anmDown.AnmFinishedHandler += new EventHandler(FinishedHandler);

            ae.Anm = this;// should be at the bottom to override ae.anm = rectmoveanm
            anmElement = ae;
        }
        public void Init()
        {
            anmElement.Visible = true;
        }
        public void Start()
        {
            anmElement.Visible = true;
            anmUp.Start();
        }
        public void Step()
        {
            if (anmUp.IsActive) anmUp.Step();
            else if (anmDown.IsActive) anmDown.Step();
        }
        public void Finish()
        {
            anmElement.Visible = true;
            anmUp.Abort();
            anmDown.Finish();
        }
        public void Abort()
        {
            anmElement.Visible = true;
            anmUp.Abort();
            anmDown.Abort();
        }
        public event EventHandler AnmFinishedHandler;
        public bool IsActive
        {
            get { return anmUp.IsActive || anmDown.IsActive; }
        }


        protected void TurningPointHandler(object o, EventArgs e)
        {
            anmDown.Start();
        }
        protected void FinishedHandler(object o, EventArgs e)
        {
            if (AnmFinishedHandler != null) AnmFinishedHandler(this, new EventArgs());
        }

    }

    public class MagnifyAnm : IAnm
    {
        protected RectMoveAnm anmMag;
        protected RectMoveAnm anmShl;
        protected IAnmElement anmElement;

        public MagnifyAnm(IAnmElement ae, int inflation, int duration)
        {
            Rectangle maged = new Rectangle(ae.BoundingBox.Left, ae.BoundingBox.Top
                , ae.BoundingBox.Width, ae.BoundingBox.Height);
            maged.Inflate(inflation, inflation);
            anmMag = new RectMoveAnm(ae, ae.BoundingBox, maged, duration / 2, RectMoveAnm.AnmType.Cubic);
            anmMag.AnmFinishedHandler += new EventHandler(TurningPointHandler);
            anmShl = new RectMoveAnm(ae, maged, ae.BoundingBox, duration / 2, RectMoveAnm.AnmType.Cubic);
            anmShl.AnmFinishedHandler += new EventHandler(FinishedHandler);

            ae.Anm = this;// should be at the bottom to override ae.anm = rectmoveanm
            anmElement = ae;
        }
        public void Init()
        {
            anmElement.Visible = true;
        }
        public void Start()
        {
            anmElement.Visible = true;
            anmMag.Start();
        }
        public void Step()
        {
            if (anmMag.IsActive) anmMag.Step();
            else if (anmShl.IsActive) anmShl.Step();
        }
        public void Finish()
        {
            anmElement.Visible = true;
            anmMag.Abort();
            anmShl.Finish();
        }
        public void Abort()
        {
            anmElement.Visible = true;
            anmMag.Abort();
            anmShl.Abort();
        }
        public event EventHandler AnmFinishedHandler;
        public bool IsActive
        {
            get { return anmMag.IsActive || anmShl.IsActive; }
        }


        protected void TurningPointHandler(object o, EventArgs e)
        {
            anmShl.Start();
        }
        protected void FinishedHandler(object o, EventArgs e)
        {
            if (AnmFinishedHandler != null) AnmFinishedHandler(this, new EventArgs());
        }

    }

}
